﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;

namespace WCFMastering.Client
{
    public static class SelfMetadataHelper
    {
        public static ServiceEndpoint[] GetEndpoints(string mexAddress)
        {
            MetadataExchangeClient client = new MetadataExchangeClient(new Uri(mexAddress), MetadataExchangeClientMode.HttpGet);
            WsdlImporter importor = new WsdlImporter(client.GetMetadata());
            return importor.ImportAllEndpoints().ToArray();
        }

        public static ServiceEndpoint[] GetEndpoints(string mexAddress, Type contractType)
        {
            ContractDescription contractDescription = ContractDescription.GetContract(contractType);
            return GetEndpoints(mexAddress, contractDescription.Name, contractDescription.Namespace);
        }

        public static ServiceEndpoint[] GetEndpoints(string mexAddress, string contractName, string contractNamespace)
        {
            ServiceEndpoint[] allEndpoints = GetEndpoints(mexAddress); 
            return allEndpoints.Where(endpoint => (endpoint.Contract.Name == contractName &&
                                                   endpoint.Contract.Namespace == contractNamespace))
                               .ToArray();
        }

        public static string[] GetAddresses(string mexAddress, Type contractType, Type bindingType)
        {
            ServiceEndpoint[] allEndpoints = GetEndpoints(mexAddress, contractType);
            return allEndpoints.Where(endpoint =>endpoint.Binding.GetType()==bindingType)
                               .Select(endpoint=>endpoint.Address.Uri.AbsoluteUri).ToArray();
        }

        public static ContractDescription[] GetContracts(string mexAddress)
        {
            MetadataExchangeClient client = new MetadataExchangeClient(new Uri(mexAddress), MetadataExchangeClientMode.HttpGet);
            WsdlImporter importor = new WsdlImporter(client.GetMetadata());
            return importor.ImportAllContracts().ToArray();
        }

        public static ContractDescription[] GetContracts(string mexAddress,Type bindingType )
        {
            ServiceEndpoint[] allEndpoints = GetEndpoints(mexAddress);
            return allEndpoints.Where(endpoint => endpoint.Binding.GetType() == bindingType)
                               .Select(endpoint => endpoint.Contract)
                               .ToArray();
        }

        public static string[] GetOperations(string mexAddress, Type contractType)
        {
            ServiceEndpoint[] allEndpoints = GetEndpoints(mexAddress, contractType); 

            return allEndpoints.Aggregate(new List<string>(), (operations, endpoint) =>
            {
                 operations.AddRange(endpoint.Contract.Operations.Select(od=>od.Name));
                 return operations;
            }).ToArray();
        }

        public static string[] GetOperations(string mexAddress, string contractName, string contractNamespace)
        {
            ServiceEndpoint[] allEndpoints = GetEndpoints(mexAddress, contractName, contractNamespace);
 
            return allEndpoints.Aggregate(new List<string>(), (operations, endpoint) =>
            {
                operations.AddRange(endpoint.Contract.Operations.Select(od => od.Name));
                return operations;
            }).ToArray();
        }

        public static bool QueryContract(string mexAddress, Type contractType)
        {
            return GetEndpoints(mexAddress, contractType).Count() > 0;
        }

        public static bool QueryContract(string mexAddress, string contractName, string contractNamespace)
        {
            return GetEndpoints(mexAddress, contractName, contractNamespace).Count() > 0;
        }
    }
}
